/*
 * 描述： <描述>
 * 修改人： rain
 * 修改时间： 2016年4月7日
 * 项目： rainhy-webcore
 */
package com.rainhy.webcore.transaction.context;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import com.rainhy.webcore.util.UUIDUtils;

/**
 * 事务容器
 * 
 * @author rain
 * @version [版本号, 2016年4月7日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public class TransactionContext extends TransactionContextConfigurator implements InitializingBean {
    
    /** 自身唯一引用 */
    private static TransactionContext context;
    
    /**
     * 
     * 根据事务传播性开启一个新的事务来执行方法<br>
     * 此事务名默认为:"Rainhy.TransactionName"<br>
     * 此事务传播方式默认为:{@link TransactionDefinitionEnum#PROPAGATION_REQUIRED}
     *
     * @param transactionDefinitionEnum 事务传播性
     * @param runnable 执行方法
     * 
     * @return void [返回类型说明]
     * @exception [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年9月15日]
     * @author rain
     */
    public static void execute(Runnable runnable) {
        execute(TransactionDefinitionEnum.PROPAGATION_REQUIRED, runnable);
    }
    
    /**
     * 
     * 根据事务传播性开启一个新的事务来执行方法
     *
     * @param transactionName 事务名
     * @param transactionDefinitionEnum 事务传播性
     * @param runnable 执行方法
     * 
     * @return void [返回类型说明]
     * @exception [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年9月15日]
     * @author rain
     */
    public static void execute(String transactionName, TransactionDefinitionEnum transactionDefinitionEnum, Runnable runnable) {
        getContext().executeTx(transactionName, transactionDefinitionEnum, runnable);
    }
    
    /**
     * 
     * 根据事务传播性开启一个新的事务来执行方法<br>
     * 此事务传播方式默认为:{@link TransactionDefinitionEnum#PROPAGATION_REQUIRED}
     *
     * @param transactionDefinitionEnum 事务传播性
     * @param runnable 执行方法
     * 
     * @return void [返回类型说明]
     * @exception [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年9月15日]
     * @author rain
     */
    public static void execute(String transactionName, Runnable runnable) {
        execute(transactionName, TransactionDefinitionEnum.PROPAGATION_REQUIRED, runnable);
    }
    
    /**
     * 
     * 根据事务传播性开启一个新的事务来执行方法<br>
     * 此事务名默认为:"Rainhy.TransactionName"
     *
     * @param transactionDefinitionEnum 事务传播性
     * @param runnable 执行方法
     * 
     * @return void [返回类型说明]
     * @exception [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年9月15日]
     * @author rain
     */
    public static void execute(TransactionDefinitionEnum transactionDefinitionEnum, Runnable runnable) {
        execute("Rainhy.TransactionName." + UUIDUtils.generateUUIDjdk(), transactionDefinitionEnum, runnable);
    }
    
    /**
     * 返回自身唯一引用
     *
     * @return
     * 
     * @return TransactionContext [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年4月7日]
     * @author rain
     */
    public static TransactionContext getContext() {
        return TransactionContext.context;
    }
    
    @Override
    public void afterPropertiesSet() throws Exception {
        TransactionContext.context = this;
        super.afterPropertiesSet();
    }
    
    /**
     * 
     * 根据事务传播性开启一个新的事务来执行方法
     *
     * @param transactionName 事务名
     * @param transactionDefinitionEnum 事务传播性
     * @param runnable 执行方法
     * 
     * @return void [返回类型说明]
     * @exception [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年9月15日]
     * @author rain
     */
    public void executeTx(String transactionName, TransactionDefinitionEnum transactionDefinitionEnum, Runnable runnable) {
        PlatformTransactionManager transactionManager = getTransactionManager();
        DefaultTransactionDefinition defaultTransactionDefinition = new DefaultTransactionDefinition();
        defaultTransactionDefinition.setName(transactionName);
        defaultTransactionDefinition.setPropagationBehavior(transactionDefinitionEnum.getPropagationBehavior());
        TransactionStatus status = transactionManager.getTransaction(defaultTransactionDefinition);
        try {
            runnable.run();
        } catch (Exception e) {
            transactionManager.rollback(status);
            logger.warn("事务执行出现异常", e);
            throw e;
        }
        transactionManager.commit(status);
    }
}
